package com.test.version3future;

import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author: zhangzeli
 * @date 10:07 2018/4/21
 * <P></P>
 */
public class T {

    public static void main(String[] args) {

        System.out.println("i love you  我爱你");
        ConcurrentHashMap c = new ConcurrentHashMap();
        System.out.println(c.put("1", "1"));
        System.out.println(c.put("1", "2"));
        System.out.println(c.get("1"));
        t2();

    }

    public static void t1(){
        System.out.println("my favorite product".charAt(0));
        Shop shop = new Shop("BestShop");
        long start = System.nanoTime();
        Future<Double> futurePrice = shop.getPriceAsync("my favorite product");
        long incocationTime = (System.nanoTime() - start) / 1_000_000;
        System.out.println("执行时间:" + incocationTime + " msecs");
        try {
            Double price = futurePrice.get();
            System.out.printf("Price is %.2f%n", price);
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
        long retrievalTime = (System.nanoTime() - start) / 1_000_000;
        System.out.println("retrievalTime:" + retrievalTime + " msecs");
    }

    public static void t2(){
        //验证findprices的正确性和执行性能
        long start = System.nanoTime();
        //System.out.println(findprices("myPhones27s"));
        //System.out.println(parallelFindprices("myPhones27s"));
        System.out.println(asyncFindprices("myPhones27s"));
        long duration = (System.nanoTime() - start) / 1_000_000;
        System.out.println("Done in " + duration+" msecs");
    }
    //案例:最佳价格查询器
    private static List<Shop> shops = Arrays.asList(new Shop("BestPrice"),
        new Shop(":LetsSaveBig"),
        new Shop("MyFavoriteShop"),
        new Shop("BuyItAll"));

    /**
     * 最佳价格查询器
     *
     * @param product 商品
     * @return
     */
    public static List<String> findprices(String product) {
        return shops
            .stream()
            .map(shop -> String.format("%s price is %.2f", shop.getName(), shop.getPrice(product)))
            .collect(Collectors.toList());
    }

    /**
     * 最佳价格查询器(并行流)
     *
     * @param product 商品
     * @return
     */
    public static List<String> parallelFindprices(String product) {
        return shops
            .parallelStream()
            .map(shop -> String.format("%s price is %.2f", shop.getName(), shop.getPrice(product)))
            .collect(Collectors.toList());
    }

    /**
     * 最佳价格查询器(异步调用实现)
     * @param product 商品
     * @return
     */
    public static List<String> asyncFindprices(String product) {
        //使用这种方式,你会得到一个List<CompletableFuture<String>>,列表中的每一个CompletableFuture对象在计算完成后都包含商店的String类型的名称.
        //但是,由于你用CompletableFuture实现了asyncFindprices方法要求返回一个List<String>.你需要等待所有的future执行完毕,将其包含的值抽取出来,填充到列表中才能返回
        List<CompletableFuture<String>> priceFuture = shops
            .stream()
            .map(shop -> CompletableFuture.supplyAsync(() -> String.format("%s price is %.2f", shop.getName(), shop.getPrice(product))))
            .collect(Collectors.toList());
        //为了实现这个效果,我门可以向最初的List<CompletableFuture<String>>施加第二个map操作,对list中的每一个future对象执行join操作,一个接一个地等待他们允许结束,join和get方法
        //有相同的含义,不同的在于join不会抛出任何检测到的异常
        return priceFuture
            .stream()
            .map(CompletableFuture::join)
            .collect(Collectors.toList());
    }


}

class Shop{
    private String name ;

    public Shop(String name) {
        this.name = name;
    }
    public double getPrice(String product) {
        return calculatePrice(product);
    }

    /**
     * 同步计算商品价格的方法
     *
     * @param product 商品名称
     * @return 价格
     */
    private  double calculatePrice(String product) {
        Random random = new Random();
        delay();
        return random.nextDouble() * product.charAt(0) + product.charAt(1);
    }
    /**
     * 模拟计算,查询数据库等耗时
     */
    public static void delay() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * 异步计算商品的价格.
     *
     * @param product 商品名称
     * @return 价格
     */
    public Future<Double> getPriceAsync(String product) {
        CompletableFuture<Double> futurePrice = new CompletableFuture<>();
        new Thread(() -> {
            double price = calculatePrice(product);
            futurePrice.complete(price);
        }).start();
        return futurePrice;
    }

    public String getName() {
        return name;
    }





}




